"""
配置加密模块

提供敏感信息的加密存储和解密功能
"""

import base64
import os
from cryptography.fernet import Fernet
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
from pathlib import Path
from typing import Optional


class ConfigEncryption:
    """配置加密管理器"""
    
    def __init__(self, password: Optional[str] = None):
        """
        初始化加密管理器
        
        Args:
            password: 加密密码，如果为None则从环境变量获取
        """
        self.password = password or os.getenv("CONFIG_ENCRYPTION_PASSWORD", "default_password")
        self._key = None
    
    def _get_key(self) -> bytes:
        """获取加密密钥"""
        if self._key is None:
            # 使用固定的盐值（在生产环境中应该使用随机盐值并安全存储）
            salt = b'gamer520_salt_key'
            kdf = PBKDF2HMAC(
                algorithm=hashes.SHA256(),
                length=32,
                salt=salt,
                iterations=100000,
            )
            key = base64.urlsafe_b64encode(kdf.derive(self.password.encode()))
            self._key = key
        return self._key
    
    def encrypt(self, data: str) -> str:
        """
        加密字符串
        
        Args:
            data: 要加密的字符串
            
        Returns:
            加密后的字符串（base64编码）
        """
        f = Fernet(self._get_key())
        encrypted_data = f.encrypt(data.encode())
        return base64.urlsafe_b64encode(encrypted_data).decode()
    
    def decrypt(self, encrypted_data: str) -> str:
        """
        解密字符串
        
        Args:
            encrypted_data: 加密的字符串（base64编码）
            
        Returns:
            解密后的字符串
        """
        try:
            f = Fernet(self._get_key())
            decoded_data = base64.urlsafe_b64decode(encrypted_data.encode())
            decrypted_data = f.decrypt(decoded_data)
            return decrypted_data.decode()
        except Exception as e:
            raise ValueError(f"解密失败: {e}")
    
    def encrypt_file(self, file_path: str, output_path: Optional[str] = None) -> str:
        """
        加密文件
        
        Args:
            file_path: 要加密的文件路径
            output_path: 输出文件路径，如果为None则在原文件名后添加.enc
            
        Returns:
            加密文件的路径
        """
        file_path = Path(file_path)
        if output_path is None:
            output_path = file_path.with_suffix(file_path.suffix + '.enc')
        else:
            output_path = Path(output_path)
        
        with open(file_path, 'r', encoding='utf-8') as f:
            content = f.read()
        
        encrypted_content = self.encrypt(content)
        
        with open(output_path, 'w', encoding='utf-8') as f:
            f.write(encrypted_content)
        
        return str(output_path)
    
    def decrypt_file(self, encrypted_file_path: str, output_path: Optional[str] = None) -> str:
        """
        解密文件
        
        Args:
            encrypted_file_path: 加密文件路径
            output_path: 输出文件路径，如果为None则移除.enc后缀
            
        Returns:
            解密文件的路径
        """
        encrypted_file_path = Path(encrypted_file_path)
        if output_path is None:
            if encrypted_file_path.suffix == '.enc':
                output_path = encrypted_file_path.with_suffix('')
            else:
                output_path = encrypted_file_path.with_suffix('.dec')
        else:
            output_path = Path(output_path)
        
        with open(encrypted_file_path, 'r', encoding='utf-8') as f:
            encrypted_content = f.read()
        
        decrypted_content = self.decrypt(encrypted_content)
        
        with open(output_path, 'w', encoding='utf-8') as f:
            f.write(decrypted_content)
        
        return str(output_path)


def encrypt_sensitive_value(value: str, password: Optional[str] = None) -> str:
    """
    加密敏感值的便捷函数
    
    Args:
        value: 要加密的值
        password: 加密密码
        
    Returns:
        加密后的值
    """
    encryptor = ConfigEncryption(password)
    return encryptor.encrypt(value)


def decrypt_sensitive_value(encrypted_value: str, password: Optional[str] = None) -> str:
    """
    解密敏感值的便捷函数
    
    Args:
        encrypted_value: 加密的值
        password: 解密密码
        
    Returns:
        解密后的值
    """
    encryptor = ConfigEncryption(password)
    return encryptor.decrypt(encrypted_value)